#include "sfsis.h"
#include "debug.h"
SF_Boolen config_shadowResetAction(void);
Config_u gCfg_u;                            //全局配置文件
Config *gCfgPtr = SF_NULL;                  //全局配置指针
Config_Wireless *gCfgWirelessPtr = SF_NULL; //全局无线配置指针
Config_Common *gCfgCommonPtr = SF_NULL;     //通用配置指针
Config_Factory_u *gCfgFactoryPtr_u = SF_NULL;
Config_Factory *gCfgFactoryPtr = SF_NULL;         //工厂出厂配置指针
Config_Firmware *gCfgFirmwarePtr = SF_NULL;       //固件参数配置指针
Config_Mode *gCfgModePtr = SF_NULL;               //模式配置指针
Config_ModeFactory *gCfgModeFactoryPtr = SF_NULL; //模式工厂配置指针

//检查输入的寄存器对应配置在哪块配置中
Config_Type config_regSetInSection(su8 address)
{
    if (address <= CONFIG_MAP_COMMON_TAIL)
    {
        return CONFIG_COMMON;
    }
    else if (address >= CONFIG_MAP_MODE_HEAD && address <= CONFIG_MAP_MODE_TAIL)
    {
        return CONFIG_MODE;
    }
    else if (address >= CONFIG_MAP_MODEFACTORY_HEAD && address <= CONFIG_MAP_MODEFACTORY_TAIL)
    {
        return CONFIG_MODEFACTORY;
    }
    else if (address >= CONFIG_MAP_FACTORY_HEAD && address <= CONFIG_MAP_FACTORY_TAIL)
    {
        return CONFIG_FACTORY;
    }
    else if (address >= CONFIG_MAP_WIRELESS_HEAD && address <= CONFIG_MAP_WIRELESS_TAIL)
    {
        return CONFIG_WIRELESS;
    }
    else
    {
        return CONFIG_BLANK;
    }
}

void config_init(void)
{
    su16 ii = 0;
    gCfgPtr = &gCfg_u.entity;
    gCfgWirelessPtr = &gCfg_u.entity.wireless.entity;
    gCfgCommonPtr = &gCfg_u.entity.common.entity;
    gCfgFactoryPtr = &gCfg_u.entity.factory.entity;
    gCfgFirmwarePtr = &gCfg_u.entity.firmware.entity;
    gCfgModePtr = &gCfg_u.entity.mode.entity;
    gCfgModeFactoryPtr = &gCfg_u.entity.modeFactory.entity;
    for (ii = 0; ii < sizeof(Config); ii++)
    {
        gCfg_u.memory[ii] = gSCfg_u.memory[ii];
    }
    /*存储EPROM参数*/
    if ((hwl_iic_readReg((su8)(CONFIG_MAP_FIRMWARE_HEAD + CONFIG_OFFSET(Config_Firmware, version))) != gCfgFirmwarePtr->version))
    {

        DPRINT(DEBUG_INFO, "[CONFIG] New device initialing....\r\n");
        //版本号不匹配，或者eeprom完整性检查作物，说明参数不对，要将默认参数载入存储
        //刷入参数时全部刷入。读取时初始化只读取部分。
        //1.载入通用参数
        hwl_iic_write(CONFIG_MAP_COMMON_HEAD, (su8 *)gCfgPtr->common.memory, sizeof(Config_Common_u));
        hwl_delay_ms(5);
        //2.拷贝模式至存储器
        hwl_iic_write(CONFIG_MAP_MODE_HEAD, (su8 *)gCfgPtr->mode.memory, sizeof(Config_Mode_u));
        hwl_delay_ms(5);
        //3.拷贝模式出厂设置至存储器
        hwl_iic_write(CONFIG_MAP_MODEFACTORY_HEAD, (su8 *)gCfgPtr->modeFactory.memory, sizeof(Config_ModeFactory_u));
        hwl_delay_ms(5);
        //4.拷贝出场设置至存储器
        hwl_iic_write(CONFIG_MAP_FACTORY_HEAD, (su8 *)gCfgPtr->factory.memory, sizeof(Config_Factory_u));
        hwl_delay_ms(5);
        //5.载入固件参数
        hwl_iic_write(CONFIG_MAP_FIRMWARE_HEAD, (su8 *)gCfgPtr->firmware.memory, sizeof(Config_Firmware_u));
        hwl_delay_ms(5);
        //6.拷贝无线参数至存储器(清零)
        hwl_iic_write(CONFIG_MAP_WIRELESS_HEAD, (su8 *)gCfgPtr->wireless.memory, sizeof(Config_Wireless_u));
        hwl_delay_ms(5);
    }
    else
    {
        DPRINT(DEBUG_INFO, "[CONFIG] Begin loading....\r\n");
        //版本匹配，开始载入默认参数
        //1.通用参数载入
        hwl_iic_read(CONFIG_MAP_COMMON_HEAD, (su8 *)gCfgPtr->common.memory, sizeof(Config_Common));
        hwl_delay_ms(5);
        //1.固件参数载入
        hwl_iic_read(CONFIG_MAP_FIRMWARE_HEAD, (su8 *)gCfgPtr->firmware.memory, sizeof(Config_Firmware));
        hwl_delay_ms(5);
        //3.载入模式
        hwl_iic_read(CONFIG_MAP_MODE_HEAD, (su8 *)gCfgPtr->mode.memory, sizeof(Config_Mode));
        hwl_delay_ms(5);
        //4.载入模式出厂
        hwl_iic_read(CONFIG_MAP_MODEFACTORY_HEAD, (su8 *)gCfgPtr->modeFactory.memory, sizeof(Config_ModeFactory));
        hwl_delay_ms(5);
        //5.载入出场
        hwl_iic_read(CONFIG_MAP_FACTORY_HEAD, (su8 *)gCfgPtr->factory.memory, sizeof(Config_Factory));
        hwl_delay_ms(5);
        //6.载入无线参数
        hwl_iic_read(CONFIG_MAP_WIRELESS_HEAD, (su8 *)gCfgPtr->wireless.memory, sizeof(Config_Wireless));
        hwl_delay_ms(5);

        //恢复不支持掉电存储的寄存器为默认值，因为我们一股脑儿全部载入了寄存器，所以这里要再返回回去，理论上所有寄存器都支持掉电存储，但一些位置是不需要的。
        for (ii = 0; ii < sizeof(Config); ii++)
        {
            if (regAuth_Mask[ii] == AUTH_CFG_READONLY || regAuth_Mask[ii] == AUTH_CFG_SHADOW || regAuth_Mask[ii] == AUTH_CFG_SHADOW_RESET)
            {
                gCfg_u.memory[ii] = gSCfg_u.memory[ii];
            }
        }
    }
}

//通过寄存器的方式修改和配置，通常只对外部配置使用，内部一般都是用结构体访问的
SF_Boolen config_setReg(su8 address, su8 value)
{
    SF_Boolen ret = SF_True;
    switch (regAuth_Mask[address])
    {
    case AUTH_CFG_DIRECT:
        gCfg_u.memory[address] = value;
        hwl_iic_writeReg(address, value);
        hwl_delay_ms(5); //每次操作间隔必须5ms以上...
        break;
    case AUTH_CFG_INDIRECT:
        gCfg_u.memory[address] = value;
        break;
    case AUTH_CFG_SHADOW:
        gCfg_u.memory[address] = value;
        break;
    case AUTH_CFG_SHADOW_RESET:
        gCfg_u.memory[address] = value;
        ret = config_shadowResetAction();
    case AUTH_CFG_READONLY:
        ret = SF_False;
    default:
        break;
    }
    return ret;
}

//多个地址读写，如果不支持写的会忽略错误，写完成以后会进行一次判读
SF_Boolen config_setMultRegs(su8 startAddress, su8 *buf, su8 count)
{
    SF_Boolen ret = SF_True;
    su16 tmp = 0;
    su16 tmpCnt = 0;
    SF_Boolen isNeedDirect = SF_False;
    tmpCnt = startAddress + count;
    if (tmpCnt > 255)
    {
        tmpCnt = 255;
    }
    DPRINT(DEBUG_INFO, "[CONFIG] Set [%d] to [%d], Count:%d.\r\n", startAddress, tmpCnt - 1, count);

    for (tmp = startAddress; tmp < tmpCnt; tmp++)
    {
        switch (regAuth_Mask[tmp])
        {
        case AUTH_CFG_INDIRECT:
            gCfg_u.memory[tmp] = *buf;
            DPRINT(DEBUG_INFO, "[CONFIG] Auth INDIRECT.\r\n");
            break;
        case AUTH_CFG_SHADOW:
            gCfg_u.memory[tmp] = *buf;
            DPRINT(DEBUG_INFO, "[CONFIG] Auth SHADOW.\r\n");
            break;
        case AUTH_CFG_SHADOW_RESET:
            gCfg_u.memory[tmp] = *buf; //shadow reset 操作时，需要对执行位进行操作
            isNeedDirect = SF_True;
            DPRINT(DEBUG_INFO, "[CONFIG] Auth SHADOW RESET.\r\n");
            break;
        case AUTH_CFG_READONLY:
            DPRINT(DEBUG_INFO, "[CONFIG] Auth READONLY.\r\n");
            break;
        case AUTH_CFG_DIRECT:
            DPRINT(DEBUG_INFO, "[CONFIG] Auth DIRECT.\r\n");
            gCfg_u.memory[tmp] = *buf;
            hwl_iic_writeReg(tmp, *buf);
            hwl_delay_ms(5); //每次操作间隔必须5ms以上...
            break;
        default:
            break;
        }
        buf++;
    }
    if (isNeedDirect == SF_True)
    {
        return config_shadowResetAction();
    }
    else
    {
        return ret;
    }
}

//通过寄存器的方式修改和配置，通常只对外部配置使用，内部一般都是用结构体访问的
su8 config_getReg(su8 address)
{
    return gCfg_u.memory[address];
}

su8 config_getMultRegs(su8 startAddress, su8 *buf, su8 getLen)
{
    su8 cnt = 0;
    su16 tmp = 0;
    su16 iMax;

    iMax = startAddress + getLen;
    DPRINT(DEBUG_INFO, "[CONFIG] Get [%d] to [%d], Count:%d.\r\n", startAddress, iMax - 1, getLen);
    if (iMax > 255)
    {
        iMax = 255;
    }
    for (tmp = startAddress; tmp < iMax; tmp++)
    {
        *buf = gCfg_u.memory[tmp];
        buf++;
        cnt++;
    }
    return cnt;
}

//仅内部使用接口，将固定块的配置刷入非易失存储，如果不支持刷入的，会直接返回SF_False
//该接口较为危险，谨慎使用
//每次写该接口，都会更新flash的完整性参数
SF_Boolen config_flush(Config_Type cfgType)
{
    SF_Boolen ret = SF_True;
    switch (cfgType)
    {
    case CONFIG_COMMON:
        hwl_iic_write(CONFIG_MAP_COMMON_HEAD, (su8 *)gCfgCommonPtr, sizeof(Config_Common));
        hwl_delay_ms(5);
        break;
    case CONFIG_MODE:
        hwl_iic_write(CONFIG_MAP_MODE_HEAD, (su8 *)gCfgModePtr, sizeof(Config_Mode));
        hwl_delay_ms(5);
        break;
    case CONFIG_MODEFACTORY:
        hwl_iic_write(CONFIG_MAP_MODEFACTORY_HEAD, (su8 *)gCfgModeFactoryPtr, sizeof(Config_ModeFactory));
        hwl_delay_ms(5);
        break;
    case CONFIG_FACTORY:
        hwl_iic_write(CONFIG_MAP_FACTORY_HEAD, (su8 *)gCfgFactoryPtr, sizeof(Config_Factory));
        hwl_delay_ms(5);
        break;
    case CONFIG_FIRMWARE:
        hwl_iic_write(CONFIG_MAP_FIRMWARE_HEAD, (su8 *)gCfgFirmwarePtr, sizeof(Config_Firmware));
        hwl_delay_ms(5);
        break;
    case CONFIG_WIRELESS:
        hwl_iic_write(CONFIG_MAP_WIRELESS_HEAD, (su8 *)gCfgWirelessPtr, sizeof(Config_Wireless));
        hwl_delay_ms(5);
        break;
    default:
        ret = SF_False;
        break;
    }
    return ret;
}

/*恢复默认配置*/
void config_restore(Config_Type cfgType)
{
    switch (cfgType)
    {
    case CONFIG_COMMON:
        hwl_iic_read(CONFIG_MAP_COMMON_HEAD, (su8 *)gCfgCommonPtr, sizeof(Config_Common));
        break;
    case CONFIG_MODE:
        hwl_iic_read(CONFIG_MAP_MODE_HEAD, (su8 *)gCfgModePtr, sizeof(Config_Mode));
        break;
    case CONFIG_MODEFACTORY:
        hwl_iic_read(CONFIG_MAP_MODEFACTORY_HEAD, (su8 *)gCfgModeFactoryPtr, sizeof(Config_ModeFactory));
        break;
    case CONFIG_FACTORY:
        hwl_iic_read(CONFIG_MAP_FACTORY_HEAD, (su8 *)gCfgFactoryPtr, sizeof(Config_Factory));
        break;
    case CONFIG_FIRMWARE:
        hwl_iic_read(CONFIG_MAP_FIRMWARE_HEAD, (su8 *)gCfgFirmwarePtr, sizeof(Config_Firmware));
        break;
    case CONFIG_WIRELESS:
        hwl_iic_read(CONFIG_MAP_WIRELESS_HEAD, (su8 *)gCfgWirelessPtr, sizeof(Config_Wireless));
        break;
    case CONFIG_BLANK:
        hwl_iic_read(CONFIG_MAP_BLANK_HEAD, (su8 *)&gCfg_u.memory[CONFIG_MAP_BLANK_HEAD], CONFIG_MAP_BLANK_TAIL - CONFIG_MAP_BLANK_HEAD + 1);
        break;
    default:
        break;
    }
}